
#pragma once
#include "jamain.h"
#include "jawinform.h"


_JIN_BEGIN


template<typename t_WinApp>
class CWinApp32T : public CApplication
{
public:
	CWinApp32T(void) {
		::CoInitialize(Null);
	}
	virtual ~CWinApp32T(void) {
		::CoUninitialize();
	}
	static t_WinApp* AppInstance(void) {
		return (t_WinApp*)s_inst;
	}

public:
	void PreRegisterWindowClass(WNDCLASSEX&) {
	}
	void PreCreateWindow(CREATESTRUCT&) {
	}
	Bool PreShowWindow(HWND, INT&) {
		return True;
	}
	Bool PreTranslateMessage(LPMSG) {
		return False;
	}
	void UpdateFrame(HWND, LPMSG pMsg) {
		if (!pMsg) ::WaitMessage();
	}
	Int OnCreate(HWND, LPCREATESTRUCT) {
		return 0;
	}
	void OnDestroy(HWND) {
	}
	LRESULT MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
	}

private:
	virtual Int Main(const Argv&)
	{
		t_WinApp* myApp = AppInstance();

		if (!m_MainForm.RegisterWindowClass([&](WNDCLASSEX& wc){
				wc.lpfnWndProc = _WindowProc;
				myApp->PreRegisterWindowClass(wc);
			}))
			return R_Fail;

		if (!m_MainForm.CreateWindowForm(
			[&](CREATESTRUCT& cs){ myApp->PreCreateWindow(cs); },
			[&](HWND hWnd, INT& nShow)->BOOL{ return myApp->PreShowWindow(hWnd, nShow);} 
		))
			return R_Fail;

		Int ret = m_MainForm.MessageLoop(
			[&](HWND hWnd, LPMSG pMsg){ myApp->UpdateFrame(hWnd, pMsg); }, 
			[&](LPMSG pMsg)->BOOL{ return myApp->PreTranslateMessage(pMsg); }
		);

		return ret;
	}

	static LRESULT WINAPI _WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		switch (uMsg)
		{
		case WM_CREATE:
			return AppInstance()->OnCreate(hWnd, (LPCREATESTRUCT)lParam);
		case WM_DESTROY:
			AppInstance()->OnDestroy(hWnd);
			::PostQuitMessage(R_OK);
			return 0;
		}
		return AppInstance()->MessageHandler(hWnd, uMsg, wParam, lParam);
	}

protected:
	CWinForm	m_MainForm;
};


_JIN_END

